﻿#include "trianglewindow.h"
#include <QDebug>
#include <QImage>

static const char *vertexShaderSource =
    "attribute highp vec4 posAttr;\n"
    "attribute lowp vec4 colAttr;\n"
    "varying lowp vec4 col;\n"
    "uniform highp mat4 matrix;\n"
    "attribute vec2 a_texcoord;\n"
    "varying vec2 v_texcoord;\n"
    "void main() {\n"
    "   col = colAttr;\n"
    "   gl_Position = matrix * posAttr;\n"
    "   v_texcoord = a_texcoord;\n"
    "}\n";

static const char *fragmentShaderSource =
    "varying lowp vec4 col;\n"
    "uniform sampler2D texture;\n"
    "varying highp vec2 v_texcoord;\n"
    "void main() {\n"
    "   gl_FragColor = col;\n"
    "}\n";
//texture2D(texture, v_texcoord)
struct VertexData
{
    QVector3D position;
    QVector3D color;
};

TriangleWindow::TriangleWindow()
    :m_program(0)
    ,m_frame(0)
{

}

TriangleWindow::~TriangleWindow()
{
    glDeleteBuffers(1, &VBO);
}

void TriangleWindow::initialize()
{
    //创建着色器程序
    m_program = new QOpenGLShaderProgram(this);
    //编译代码-添加顶点着色器
    m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSource);
    //编译代码-添加片段着色器
    m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSource);

    //链接着色器
    m_program->link();

    //得到顶点属性名在着色器参数列表中的位置-0
    m_posAttr = m_program->attributeLocation("posAttr");
    //得到颜色属性名在着色器参数列表中的位置-1
    m_colAttr = m_program->attributeLocation("colAttr");
    //得到矩阵规格名在着色器参数列表中的位置-0
    m_matrixUniform = m_program->uniformLocation("matrix");
    //得到纹理属性名在着色器参数列表中的位置-2
    m_texcoordLocation = m_program->attributeLocation("a_texcoord");

    //1 使用glGenBuffers函数生成一个缓冲ID
    glGenBuffers(1, &VBO);
    //2 使用glBindBuffer函数把新创建的缓冲绑定到GL_ARRAY_BUFFER缓冲类型上
    glBindBuffer(GL_ARRAY_BUFFER, VBO);

}

void TriangleWindow::render()
{
    //分辨率比例-1
    const qreal retinaScale = devicePixelRatio();

    //重置视口
    glViewport(0, 0, width() * retinaScale, height() * retinaScale);

    //清除颜色缓冲区
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glEnable(GL_DEPTH_TEST);

    //绑定着色器程序到活动的上下文
    m_program->bind();

    //4x4 矩阵
    QMatrix4x4 matrix;
    //乘以一个矩阵，为了建立透视投影矩阵
    matrix.perspective(60.0f, 4.0f/3.0f, 0.1f, 100.0f);
    //乘以这个矩阵，通过向量转换坐标
    matrix.translate(0, 0, -4);
    //乘以这个矩阵，通过向量上的角度旋转坐标
    matrix.rotate(60*m_frame / screen()->refreshRate(), 1, 1, 0);
//    matrix.rotate(30, 1,0,0);

    //设置矩阵数据
    m_program->setUniformValue(m_matrixUniform, matrix);

    //使用纹理单元
//    m_program->setUniformValue("texture", 0);

    //顶点坐标
    QVector3D vertices[] = {
        //正面
        QVector3D(-0.5f, 0.0f, 0.5f),     //1
        QVector3D(0.5f, 0.0f, 0.5f),      //2
        QVector3D(0.5f, 1.0f, 0.5f),      //3
        QVector3D(-0.5f, 1.0f, 0.5f),     //4

        //右面
        QVector3D(0.5f, 0.0f, 0.5f),       //2
        QVector3D(0.5f, 0.0f, -0.5f),      //5
        QVector3D(0.5f, 1.0f, -0.5f),      //6
        QVector3D(0.5f, 1.0f, 0.5f),       //3

        //左面
        QVector3D(-0.5f, 0.0f, 0.5f),      //1
        QVector3D(-0.5f, 0.0f, -0.5f),     //8
        QVector3D(-0.5f, 1.0f, -0.5f),     //7
        QVector3D(-0.5f, 1.0f, 0.5f),      //4

        //背面
        QVector3D(0.5f, 0.0f, -0.5f),      //5
        QVector3D(0.5f, 1.0f, -0.5f),      //6
        QVector3D(-0.5f, 1.0f, -0.5f),     //7
        QVector3D(-0.5f, 0.0f, -0.5f),     //8

        //顶面
        QVector3D(0.5f, 1.0f, 0.5f),       //3
        QVector3D(0.5f, 1.0f, -0.5f),      //6
        QVector3D(-0.5f, 1.0f, -0.5f),     //7
        QVector3D(-0.5f, 1.0f, 0.5f),      //4

        //底面
        QVector3D(0.5f, 0.0f, 0.5f),       //2
        QVector3D(0.5f, 0.0f, -0.5f),      //5
        QVector3D(-0.5f, 0.0f, -0.5f),     //8
        QVector3D(-0.5f, 0.0f, 0.5f),      //1

    };

    //颜色值
    QVector3D colors[] = {
        //正面
        QVector3D(1.0f, 0.0f, 0.0f),   //1 红
        QVector3D(0.0f, 1.0f, 0.0f),   //2 绿
        QVector3D(0.0f, 0.0f, 1.0f),   //3 蓝
        QVector3D(1.0f, 1.0f, 1.0f),   //4 白

        //右面
        QVector3D(0.0f, 1.0f, 0.0f),   //2 绿
        QVector3D(1.0f, 1.0f, 0.0f),   //5 黄
        QVector3D(0.0f, 1.0f, 1.0f),   //6 青
        QVector3D(0.0f, 0.0f, 1.0f),   //3 蓝

        //左面
        QVector3D(1.0f, 0.0f, 0.0f),   //1 红
        QVector3D(1.0f, 0.0f, 1.0f),   //8 紫
        QVector3D(1.0f, 0.6f, 0.0f),   //7 橘
        QVector3D(1.0f, 1.0f, 1.0f),   //4 白

        //背面
        QVector3D(1.0f, 1.0f, 0.0f),   //5 黄
        QVector3D(0.0f, 1.0f, 1.0f),   //6 青
        QVector3D(1.0f, 0.6f, 0.0f),   //7 橘
        QVector3D(1.0f, 0.0f, 1.0f),   //8 紫

        //顶面
        QVector3D(0.0f, 0.0f, 1.0f),   //3 蓝
        QVector3D(0.0f, 1.0f, 1.0f),   //6 青
        QVector3D(1.0f, 0.6f, 0.0f),   //7 橘
        QVector3D(1.0f, 1.0f, 1.0f),   //4 白

        //底面
        QVector3D(0.0f, 1.0f, 0.0f),   //2 绿
        QVector3D(1.0f, 1.0f, 0.0f),   //5 黄
        QVector3D(1.0f, 0.0f, 1.0f),   //8 紫
        QVector3D(1.0f, 0.0f, 0.0f),   //1 红

    };

    //vbo数据，顶点与颜色
    VertexData vc[] = {
        //正面
        {QVector3D(-0.5f, 0.0f, 0.5f), QVector3D(1.0f, 0.0f, 0.0f)},     //1
        {QVector3D(0.5f, 0.0f, 0.5f), QVector3D(0.0f, 1.0f, 0.0f)},      //2
        {QVector3D(0.5f, 1.0f, 0.5f), QVector3D(0.0f, 0.0f, 1.0f)},      //3
        {QVector3D(-0.5f, 1.0f, 0.5f), QVector3D(1.0f, 1.0f, 1.0f)},     //4

        //右面
        {QVector3D(0.5f, 0.0f, 0.5f),  QVector3D(0.0f, 1.0f, 0.0f)},     //2
        {QVector3D(0.5f, 0.0f, -0.5f), QVector3D(1.0f, 1.0f, 0.0f)},     //5
        {QVector3D(0.5f, 1.0f, -0.5f), QVector3D(0.0f, 1.0f, 1.0f)},     //6
        {QVector3D(0.5f, 1.0f, 0.5f),  QVector3D(0.0f, 0.0f, 1.0f)},     //3

        //左面
        {QVector3D(-0.5f, 0.0f, 0.5f), QVector3D(1.0f, 0.0f, 0.0f)},     //1
        {QVector3D(-0.5f, 0.0f, -0.5f),QVector3D(1.0f, 0.0f, 1.0f)},     //8
        {QVector3D(-0.5f, 1.0f, -0.5f),QVector3D(1.0f, 0.6f, 0.0f)},     //7
        {QVector3D(-0.5f, 1.0f, 0.5f), QVector3D(1.0f, 1.0f, 1.0f)},     //4

        //背面
        {QVector3D(0.5f, 0.0f, -0.5f),   QVector3D(1.0f, 1.0f, 0.0f)},   //5
        {QVector3D(0.5f, 1.0f, -0.5f),   QVector3D(0.0f, 1.0f, 1.0f)},   //6
        {QVector3D(-0.5f, 1.0f, -0.5f),  QVector3D(1.0f, 0.6f, 0.0f)},   //7
        {QVector3D(-0.5f, 0.0f, -0.5f),  QVector3D(1.0f, 0.0f, 1.0f)},   //8

        //顶面
        {QVector3D(0.5f, 1.0f, 0.5f),    QVector3D(0.0f, 0.0f, 1.0f)},   //3
        {QVector3D(0.5f, 1.0f, -0.5f),   QVector3D(0.0f, 1.0f, 1.0f)},   //6
        {QVector3D(-0.5f, 1.0f, -0.5f),  QVector3D(1.0f, 0.6f, 0.0f)},   //7
        {QVector3D(-0.5f, 1.0f, 0.5f),   QVector3D(1.0f, 1.0f, 1.0f)},   //4

        //底面
        {QVector3D(0.5f, 0.0f, 0.5f),    QVector3D(0.0f, 1.0f, 0.0f)},   //2
        {QVector3D(0.5f, 0.0f, -0.5f),   QVector3D(1.0f, 1.0f, 0.0f)},   //5
        {QVector3D(-0.5f, 0.0f, -0.5f),  QVector3D(1.0f, 0.0f, 1.0f)},   //8
        {QVector3D(-0.5f, 0.0f, 0.5f),   QVector3D(1.0f, 0.0f, 0.0f)},   //1
    };

    //3 把用户定的义数据复制到当前绑定缓冲的函数
    glBufferData(GL_ARRAY_BUFFER, sizeof(vc), vc, GL_STATIC_DRAW);

    //4 链接顶点属性
    //indx: 属性名
    //size: 顶点大小
    //type: 数据类型
    //normalized：数据被标准化
    //stride: 步长
    //ptr: 数据在缓冲中起始位置的偏移量
    glVertexAttribPointer(m_posAttr, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), (GLvoid*)0);
    glVertexAttribPointer(m_colAttr, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), (GLvoid*)sizeof(QVector3D));

    //5 开启顶点属性
    glEnableVertexAttribArray(0);
    //颜色值
    glEnableVertexAttribArray(1);

    //6 绘制四边形
    glDrawArrays(GL_QUADS, 0, 24);

    //7 停用对应的顶点属性数组
    glDisableVertexAttribArray(1);
    glDisableVertexAttribArray(0);

    //释放程序
    m_program->release();

    m_frame++;

}
